<!--
 * @Date: 2024-04-08 15:19:12
 * @Author: LiSong
 * @LastEditors: LiSong
 * @LastEditTime: 2025-01-21 15:32:51
 * @Description: 数字输入框
-->
<template>
  <el-input-number
    :="compAttrs"
    :style="compStyle"
    v-model="compValue"
    @input="onInput"
    @change="onChange"
    @focus="onFocus($event)"
  >
  </el-input-number>
</template>

<script setup>
import { NumberUtils } from '/@/utils';
import { watch, useAttrs, computed } from 'vue';

// 向上的事件
const emits = defineEmits(['update:modelValue', 'change', 'input'])
// 传递的属性
const attrs = useAttrs()
// 属性的定义
const props = defineProps({
  // 最小值
  min: { type: Number },
  // 最大值
  max: { type: Number },
  // 输入框宽度
  width: { type: [Number, String], default: 100 },
  // 存在下划线
  undeline: { type: Boolean, default: true },
  // 自动宽度
  autoWidth: { type: Boolean, default: false },
  // 数值精度
  precision: { type: Number, default: 2 },
  // 全选内容
  selectAll: { type: Boolean, default: false },
  // 选中项绑定值
  modelValue: { type: [String, Number] },
})

// 组件值
const compValue = ref(void 0)
// 组件的配置
const compAttrs = computed(() => {
  const resAttrs = { controls: false }
  if (isNotEmpty(props.min)) resAttrs.min = props.min
  if (isNotEmpty(props.max)) resAttrs.max = props.max
  return resAttrs
})
// 主键自定义样式
const compStyle = computed(() => {
  const { width, autoWidth } = props
  return {
    width: autoWidth ? '100%' : typeof width === 'number' ? `${width}px` : width
  }
})

/**
 * Input事件触发
 * 
 * @param value 输入的值
 */
const onInput = (value) => {
  emits('input', value)
}
/**
 * 在 Input 值改变时触发
 *
 * @param value 输入的值
 */
const onChange = (value) => {
  if (isNotEmpty(value)) {
    emits('change', NumberUtils.formatValue(value, props.precision))
  } else {
    emits('change', isNotEmpty(props.min) ? props.min : value)
  }
}
/**
 * 鼠标失去焦点事件
 *
 * @param event dom对象
 */
const onFocus = (event) => {
  // 设置是否全选内容
  if (props.selectAll) event.currentTarget.select()
}
/**
 * 是否为空
 * @param value 输入内容
 */
const isNotEmpty = (value) => {
  return !(value === '' || value === undefined || value === null)
}


watch (
  () => compValue.value,
  (nv) => {
    let value = nv
    const { min, max } = props
    // 如果值不为空
    if (isNotEmpty(value)) {
      // 如果最小值不为空
      if (isNotEmpty(min)) { value = (value < min) ? min : value }
      // 如果最大值不为空
      if (isNotEmpty(max)) { value = (value > max) ? max : value }
    } else {
      // 如果最小值不为空
      if (isNotEmpty(min)) {
        value = min
        compValue.value = min
      }
    }
    emits('update:modelValue', NumberUtils.formatValue(value, props.precision))
  }
)

watch(
  () => props.modelValue,
  (nv) => {
    if (isNotEmpty(nv)) {
      // 是否数字字符串
      if (Number.isNaN(Number(nv))) {
        compValue.value = undefined
      } else {
        compValue.value = Number(nv)
      }
    } else {
      compValue.value = undefined
    }
  },
  { deep: true, immediate: true }
)
</script>

<style lang="scss" scoped>
</style>
